package com.hu.hrm.service.impl;

import com.hu.hrm.doc.CourseDoc;
import com.hu.hrm.domain.Course;
import com.hu.hrm.domain.CourseDetail;
import com.hu.hrm.domain.CourseMarket;
import com.hu.hrm.dto.CourseSaveDTO;
import com.hu.hrm.feignclients.ESFeignClient;
import com.hu.hrm.mapper.CourseDetailMapper;
import com.hu.hrm.mapper.CourseMapper;
import com.hu.hrm.mapper.CourseMarketMapper;
import com.hu.hrm.query.CourseQuery;
import com.hu.hrm.service.ICourseService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.hu.hrm.util.AjaxResult;
import com.hu.hrm.util.LoginInfo;
import com.hu.hrm.util.PageList;
import com.hu.hrm.util.UserContext;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author woo
 * @since 2020-02-22
 */
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements ICourseService {

    //课程详细
    @Autowired
    private CourseDetailMapper courseDetailMapper ;

    //课程营销
    @Autowired
    private CourseMarketMapper courseMarketMapper ;

    //Es Feign
    @Autowired
    private ESFeignClient esFeignClient;

    @Override
    public void saveOrUpdate(CourseSaveDTO courseSaveDTO) {
        //1.保存课程 （准备参数）
        Course course = courseSaveDTO.getCourse();
        //课程状态 注意对应数据库
        course.setStatus(Course.STATUS_OFFLINE);
        //开课时间  假数据
        Date date = new Date();
        course.setStartTime(date);
        //节课时间
        course.setEndTime(date);

        //等级名字(前端要对应)  关于课程等级：可知 前端是提交的id；没有名字，有个方法：前台准备 然后直接提交
        //还有一种就是通过前端提交的id 去查等级的名字，再传入数据库； 就要注意数据库分库的问题（分了：调用对应的Mapper嘛）
        //这里用了第一种

        /** 2
         * 分析 ： 关于机构、创建课程的用户都必须要拿到当前登录对象才行撒
         * 登录对象  (session)  工具UserContext   session中拿
         * 而需要的机构id 机构名字  用户id  用户名  需要的都没有，拿的时候需要保持，所以类似dto，准备一个对象来保存 考虑到作用，放到common中了
         */
        //机构id :
        LoginInfo loginInfo = UserContext.getLoginInfo();
        course.setTenantId(loginInfo.getTenantId());
        //机构名字
        course.setTenantName(loginInfo.getTenantName());
        //创建课程的用户id
        course.setUserId(loginInfo.getUserId());

        //创建课程的用户名
        course.setUserName(loginInfo.getUserName());

        baseMapper.insert(course);

        /**
         * 分析数据库 可知 课程详情、课程营销id都是从课程中来的（表设计思想：id对应）
         * 所以注意获取的时候.....
         */
        //3.保存课程详情
        CourseDetail courseDetail = courseSaveDTO.getCourseDetail();
        courseDetail.setId(course.getId());
        courseDetailMapper.insert(courseDetail);

        //4.保存课程营销
        CourseMarket courseMarket = courseSaveDTO.getCourseMarket();
        courseMarket.setId(course.getId());
        courseMarket.setPriceOld(courseMarket.getPrice());

        //截止时间:假数据
        courseMarket.setExpires(date);

        courseMarketMapper.insert(courseMarket);
    }

    //课程上线
    /**   上线分析：
     *   课程上线（ES 注：只需要上线需要的信息，并非所有的都传入ES中，而ES是单独的服务，所以还要准备ES中的接口）
     *   这就要从course服务传数据到ES服务，两个服务都需要对数据进行封装，重点是ES需要的是文档对象
     *   所以：将文档对象抽取成公共模块 两个服务都有用了 只需要对应的创建对象来封装 就方便很多了
     *   然后：course-server通过Feign调用es-server 所还要准备ES的Feign
     *
     *   CourseController：
     *  首先可知前台传来的是选中课程的id
     *  那么第一步就该 通过id 查到课程的详细，判断这个课程上线、下线状态 （为了后面上线课程）
     *
     */
    @Override
    public void onLineCourse(Long id) {
        //1.根据id查询到选中的课程
        Course course = baseMapper.selectById(id);

        //2.判断这个课程的上下线状态，要不处于上线状态才执行下面撒（上线）
        if(course == null || course.getStatus() != Course.STATUS_OFFLINE){
            throw new RuntimeException("课程已处于上线状态");
        }
        //当课程不处于下线状态时，才执行上传（到ES，而且是选择性的上传）
        //上传（达到上线） 就要求调用ES微服务  （所以：准备ES Controller、还有Feign  以及抽取Doc文档对象）

        //在配置好ES接口、Feign、抽取了Doc文档模块 导入了依赖之后 即可注入ESFeignClient（这里是Course），执行上传
        //1.上传第一步：准备好容器
        CourseDoc courseDoc = new CourseDoc();

        //2.准备容器中的数据
        //课程营销
        System.out.println("id:"+id);
        CourseMarket courseMarket = courseMarketMapper.selectById(id);
        System.out.println("courseMarket:"+courseMarket);
        //课程详细
        CourseDetail courseDetail = courseDetailMapper.selectById(id);
        System.out.println("courseDetail:"+courseDetail);
        /* 考由于是多个表那个字段 ---> 使用工具完成数据的装入
        *   org.springframework.beans.BeanUtils;
        *   方法：copyProperties 参数：源+目标（那个考到那个）
        *   注意 两个对象的字段名一定要一样 所以Doc选字段的时候 拷贝！！
        * */

        BeanUtils.copyProperties(course,courseDoc);//拷贝课程的属性到doc

        //拷贝详情的属性到doc
        BeanUtils.copyProperties(courseDetail,courseDoc);

        //拷贝营销的属性到doc
        BeanUtils.copyProperties(courseMarket,courseDoc);


        //其他需要处理的属性（在courseMarket中Charge的字段是Long在Doc中保存的是String   因为在保存的时候0是免费....）
        //有时候在Doc里面也可以直接存  比如时间
        courseDoc.setChargeName(courseMarket.getCharge()==0?"免费":"收费");
        courseDoc.setOnlineDate(new Date());
        //假数据（数据库中暂时没存字段）：
        //预览数量
        courseDoc.setViewCount(100);
        //购买数量
        courseDoc.setBuyCount(200);

        AjaxResult ajaxResult = esFeignClient.save(courseDoc);

        if (ajaxResult.isSuccess()){
            //如果保存成功，修改数据库中的状态
            course.setStatus(Course.STATUS_ONLINE);
            baseMapper.updateById(course);
        }else{
            throw new RuntimeException("课程上线失败");
        }
    }

    //课程下线
    @Override
    public void offLineCourse(Long id) {
        //同上线，先查到课程
        Course course = baseMapper.selectById(id);

        //首先想到的应该是判断！！！  判断状态
        if (course == null || course.getStatus() != Course.STATUS_ONLINE){
            throw new RuntimeException("课程为空 或 课程已处于下线状态");
        }

        //删除ES中的课程
        AjaxResult ajaxResult = esFeignClient.deleteById(id);
        System.out.println(ajaxResult.isSuccess());

        //先判断，是上线状态 才 修改数据库中课程的状态为下线
        if(ajaxResult.isSuccess()){
            throw new RuntimeException("课程下线失败");
        }

        course.setStatus(Course.STATUS_OFFLINE);
        baseMapper.updateById(course);
    }

    //课程搜索
    @Override
    public PageList queryCourses(CourseQuery courseQuery) {
        return esFeignClient.searchCourse(courseQuery);
    }

}
